package org.bookshare.validator;

import java.io.File;
import java.io.IOException;

import org.benetech.event.EventListener;
import org.benetech.event.LoggingEventListener;
import org.benetech.util.FileUtils;
import org.bookshare.document.beans.DAISYDocumentSet;
import org.bookshare.document.beans.DocumentSet;
import org.bookshare.document.beans.DocumentType;
import org.bookshare.document.reader.DAISYReader;
import org.bookshare.document.reader.Reader;
import org.bookshare.validator.report.HTMLReportEngine;
import org.bookshare.validator.report.ReportEngine;
import org.bookshare.validator.report.ValidationMetadata;
import org.bookshare.validator.rule.NCXAndSMILExistRule;
import org.bookshare.validator.rule.OPFMetadataRule;
import org.bookshare.validator.rule.ResourcesExistRule;
import org.bookshare.validator.rule.Rule;
import org.bookshare.validator.rule.XMLDocumentsParseRule;
import org.bookshare.validator.rule.XMLPageNumbersRule;


public class DAISYValidator implements Validator<DocumentType.DAISY> {

	    /** The list of rules to run. This could be a user configurable option */
	    private static final Rule[] RULES = new Rule[] {
	    	// must come first
	    	new XMLDocumentsParseRule(),
	        new ResourcesExistRule(),
	        new OPFMetadataRule(),
	        new XMLPageNumbersRule(),
	        new NCXAndSMILExistRule(),
	    };

	    /**
	     * Default constructor.
	     */
	    public DAISYValidator() {
	    	//empty
	    }

	    /**
	     * {@inheritDoc}
	     */
	    public final ValidationMetadata validate(final DocumentSet<DocumentType.DAISY> documentSet, final EventListener listener)
	        throws IOException
	    {
	        if (documentSet == null) {
	            throw new IOException("Null document set!");
	        }

	        if (!(documentSet instanceof DAISYDocumentSet)) {
	            throw new IOException("Unable to validate documents of type: "
	                    + documentSet.getType());
	        }

	        // reporting object
	        final ValidationMetadata reportMetadata = new ValidationMetadata("DAISY");

	        reportMetadata.setDocumentSet((DAISYDocumentSet) documentSet);

	        listener.message("Automated Checks");
	        // now run the list of rules we have
	        for (Rule rule : RULES) {
	            listener.message("Evaluating rule: " + rule.getClass().getName());
	            rule.evaluate(reportMetadata, listener);
	        }

	        return reportMetadata;
	    }

	    /**
	     * {@inheritDoc}
	     */
	    public static void main(final String[] args) {
	        if (args.length < 2) {
	            System.out.println("Usage: java org.benetech.validator.daisy.DAISY"
	                    + "Validator package.zip myReportName");
	            System.exit(1);
	        }
	        final String fileName = args[0];
	        final String reportFileName = args[1];
	        final File zipFile = new File(fileName);
	        if (!zipFile.exists()) {
	            System.out.println("Package file " + zipFile + " not found.");
	            System.exit(1);
	        }

	        try {
	            final EventListener listener = new LoggingEventListener("DAISY");
	            final Reader<DocumentType.DAISY> reader = new DAISYReader();
	            reader.setTmpDir(FileUtils.getTmpDir().getAbsolutePath());
	            final DocumentSet<DocumentType.DAISY> documentSet = reader.read(zipFile, listener);
	            final DAISYValidator validator = new DAISYValidator();
	            final ValidationMetadata report = validator.validate(documentSet, listener);
	            final ReportEngine engine = new HTMLReportEngine();
	            listener.message("======> Generating report");
	            engine.generateReport(new File("."), reportFileName, report, listener);
	        } catch (IOException e) {
	            e.printStackTrace();
	            System.exit(2);
	        }
	     }
	}
